/* Copyright 2011 Jacob Palnick
   
   This library is free software; you can redistribute it and/or modify
   it under the terms of version 3 of the GNU Lesser General Public 
   License as published by the Free Software Foundation.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
   GNU Lesser General Public License for more details.
   
   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the 
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
   Boston, MA 02111-1307  USA
   
   You can contact Jacob Palnick by sending e-mail to
   jpalnick@me.com. Please include "java-dnd-character" in the
   subject line.
*/
package dndapplication.data;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author jpalnick
 */
public class DiceRoller {

    private int DieRoller(int numberOfSides, int numberOfDice, Random aRandom) {
        int sum = 0;
        for (int dieNumber = 0; dieNumber < numberOfDice; dieNumber++) {
            sum = sum + ((int) ((numberOfSides + 1) * aRandom.nextDouble())) + 1;
        }
        return sum;
    }
    
    private int STR = 4;
    private int DEX = 3;
    private int CON = 2;
    private int INT = 1;
    private int WIS = 0;
    private int CHA = -1;
    
    public void setAbilityMod(int strenght, int dexterity, int constitution, int intelligence, int wisdom, int charisma) {
    	STR = strenght;
    	DEX = dexterity;
    	CON = constitution;
    	INT = intelligence;
    	WIS = wisdom;
    	CHA = charisma;
    }
    
    public DiceRoller(int strenght, int dexterity, int constitution, int intelligence, int wisdom, int charisma) {
    	STR = strenght;
    	DEX = dexterity;
    	CON = constitution;
    	INT = intelligence;
    	WIS = wisdom;
    	CHA = charisma;
    }

    public DiceRoller() {
    	STR = 0;
    	DEX = 0;
    	CON = 0;
    	INT = 0;
    	WIS = 0;
    	CHA = 0;
    }

    public int getAbilityModifier(String ability) {
        if (ability.equalsIgnoreCase("STR")) {
            return STR;
        } else if (ability.equals("DEX")) {
            return DEX;
        } else if (ability.equals("CON")) {
            return CON;
        } else if (ability.equals("INT")) {
            return INT;
        } else if (ability.equals("WIS")) {
            return WIS;
        } else if (ability.equals("CHA")) {
            return CHA;
        }
        return 0;
    }

    /**
     * parse a dice roll string
     * @param rollString
     * @return
     */
    public String parseRoll(String rollString) {
        Random aRandom = new Random();

        //String testStr = "1.5xSTR+4d6+3d8+2d6 shocking+2d6 flaming+2d6 frezing+2d6 acid";

        String[] subStrings = rollString.split("[+|-]");

        int[] values = new int[subStrings.length];

        int valueCount = 0;

        String specialOut = "";

        for (int a = 0; a < subStrings.length; a++) {
//            System.out.println(subStrings[a]);

//            Pattern p1 = Pattern.compile(".*(STR|DEX|CON|INT|WIS|CHA).*");
//            Matcher m1 = p1.matcher(subStrings[a]);
//            System.out.println(m1.matches());
//            System.out.println(Pattern.compile(".*(STR|DEX|CON|INT|WIS|CHA).*").matcher(subStrings[a]).matches());

            if (Pattern.compile(".*(STR|DEX|CON|INT|WIS|CHA).*").matcher(subStrings[a]).matches()) {
                Pattern p = Pattern.compile(".*\\d*\\.?\\d*[xX]?.*");
                Matcher m = p.matcher(subStrings[a].trim());
                if (m.matches()) {
                    String multiplierStr = m.group();
//                    System.out.println(multiplierStr);
                    multiplierStr = multiplierStr.split("[xX]")[0];
//                    System.out.println(multiplierStr);

                    double multiplier = Double.parseDouble(multiplierStr);

//                    System.out.println("double value " + multiplier);
                    p = Pattern.compile(".*(STR|DEX|CON|INT|WIS|CHA).*");
                    m = p.matcher(subStrings[a].trim());
                    int score = 0;
                    if (m.matches()) {
//                        System.out.println("group " + m.group());
                        score = getAbilityModifier(m.group().split("[xX]")[1].trim());
                    }

//                    System.out.println("score value " + score);

                    values[valueCount++] = (int) (multiplier * score);

                } else {
                    p = Pattern.compile(".*(STR|DEX|CON|INT|WIS|CHA).*");
                    m = p.matcher(subStrings[a].trim());
                    int score = 0;
                    if (m.matches()) {
                        score = getAbilityModifier(m.group());
                    }
                    values[valueCount++] = score;
                }
            } else if (Pattern.compile(".*[dD].*").matcher(subStrings[a].trim()).matches()) {
                if (Pattern.compile(".*\\p{Space}[a-zA-Z]*.*").matcher(subStrings[a].trim()).matches()) {
                    String[] tmp = subStrings[a].trim().split("[dD]|\\p{Space}");
                    int sides = Integer.parseInt(tmp[1]);
                    int dice = Integer.parseInt(tmp[0]);
                    int result = DieRoller(sides, dice, aRandom);

//                    System.out.println("substring " + subStrings[a]);

                    String end = subStrings[a].trim().split("\\p{Space}", 2)[1];

//                    System.out.println("end :" + end);

                    specialOut = specialOut + " + " + result + " " + end;
                } else {
                    String[] tmp = subStrings[a].trim().split("[dD]|\\p{Space}");
                    int sides = Integer.parseInt(tmp[1]);
                    int dice = Integer.parseInt(tmp[0]);
                    int result = DieRoller(sides, dice, aRandom);

                    values[valueCount++] = result;
                }
            } else {
                if (Pattern.compile("\\d*\\p{Space}*[a-zA-Z]*.*").matcher(subStrings[a].trim()).matches()) {
                    String number = subStrings[a].trim().split("\\p{Space}", 2)[0];
                    String end = subStrings[a].trim().split("\\p{Space}", 2)[1];

                    int v = Integer.parseInt(number);

                    specialOut = specialOut + " + " + v + " " + end;

                } else {
                    values[valueCount++] = Integer.parseInt(subStrings[a].trim());
                }
            }
        }

        int sum = 0;

        for (int i = 0; i < valueCount; i++) {
            sum = sum + values[i];
//            System.out.println("value " + i + ": " + values[i]);
        }

        return sum + specialOut;

    }

    /*
    /**
     * @param args the command line arguments
     */
/*
    public static void main(String[] args) {

        //  prompt the user to enter their name
        System.out.println("Roll String formatting:");
        System.out.println(" -dice: to roll 4 - 6 sided dice, enter \"4d5\"");
        System.out.println(" -to add a damage type (ie shocking) just add \" shocking\" right after the role");
        System.out.println("\tfor example 4 6 side dice sith shocking damage would be \"4d6 shocking\"");
        System.out.println(" -for ability scores use the 3 letter abreviation (ie. STR)");
        System.out.println(" -you can multiply the ability modifier by adding any number and x before the");
        System.out.println("\tability. for example \"1.5xSTR\"");
        System.out.println();
        System.out.println("multiple rolls can be combined by using\"+\". for example \"4d6+2d10\"");
        System.out.println();
        System.out.println("this can also be used for other rpg dice rolls. just ignore the ability score part.");
        System.out.println();
        System.out.println("when done just type \"done\" to close");
        System.out.println();

        String input = "";
        //  open up standard input
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));


        while (!input.equals("done")) {
            System.out.print("Please enter a D&D roll string: ");




            //  read the username from the command-line; need to use try/catch with the
            //  readLine() method
            try {
                input = br.readLine();
            } catch (IOException ioe) {
                System.out.println("IO error trying to read your name!");
                System.exit(1);
            }

            if (!input.equals("done")) {
                System.out.println("Thank you, you rolled: " + parseRoll(input));
            }

        }

        // TODO code application logic here
    }
//*/
}
